package com.ruoyi.tzai.service.task.impl;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.tzai.domain.NewsArticle;
import com.ruoyi.tzai.domain.NewsContent;
import com.ruoyi.tzai.domain.TaskQueue;
import com.ruoyi.tzai.domain.TaskStep;
import com.ruoyi.tzai.service.INewsArticleService;
import com.ruoyi.tzai.service.INewsContentService;
import com.ruoyi.tzai.service.ITaskQueueService;
import com.ruoyi.tzai.service.ITaskStepService;
import com.ruoyi.tzai.service.task.IParallelProcessorService;
import com.ruoyi.tzai.service.task.ITaskExecutorService;

/**
 * 任务执行器Service业务层处理
 * 
 * @author tzai
 * @date 2025-11-12
 */
@Service
public class TaskExecutorServiceImpl implements ITaskExecutorService 
{
    private static final Logger log = LoggerFactory.getLogger(TaskExecutorServiceImpl.class);

    @Autowired
    private ITaskQueueService taskQueueService;

    @Autowired
    private ITaskStepService taskStepService;

    @Autowired
    private IParallelProcessorService parallelProcessorService;

    @Autowired
    private INewsArticleService newsArticleService;

    @Autowired
    private INewsContentService newsContentService;

    /**
     * 执行任务（异步）
     */
    @Override
    @Async("taskExecutor")
    public void executeTask(Long taskId) 
    {
        log.info("========== 开始执行任务 ========== TaskID: {}", taskId);
        
        String workerThread = Thread.currentThread().getName();
        
        try {
            // 1. 尝试锁定任务
            if (!taskQueueService.tryLockTask(taskId, workerThread)) {
                log.warn("任务锁定失败，可能已被其他线程处理: taskId={}", taskId);
                return;
            }
            
            // 2. 初始化步骤
            List<TaskStep> existingSteps = taskStepService.selectStepsByTaskId(taskId);
            if (existingSteps.isEmpty()) {
                taskStepService.initializeSteps(taskId);
            }
            
            // 3. 执行步骤1：文本清理
            executeTextCleanStep(taskId);
            
            // 4. 执行步骤2：AI处理
            executeAIProcessStep(taskId);
            
            // 5. 执行步骤3：TTS生成（中文）
            executeTTSGenerateStep(taskId, "cn");
            
            // 6. 执行步骤4：TTS生成（英文）
            executeTTSGenerateStep(taskId, "en");
            
            // 7. 完成任务
            completeTask(taskId);
            
            log.info("========== 任务执行完成 ========== TaskID: {}", taskId);
            
        } catch (Exception e) {
            log.error("任务执行失败: taskId={}", taskId, e);
            failTask(taskId, e.getMessage());
        }
    }

    /**
     * 从断点恢复任务
     */
    @Override
    @Async("taskExecutor")
    public void resumeFromBreakpoint(Long taskId) 
    {
        log.info("从断点恢复任务: taskId={}", taskId);
        
        try {
            TaskQueue task = taskQueueService.selectTaskQueueByTaskId(taskId);
            if (task == null) {
                log.error("任务不存在: taskId={}", taskId);
                return;
            }
            
            String currentStep = task.getCurrentStep();
            log.info("当前步骤: {}", currentStep);
            
            // 根据当前步骤继续执行
            if ("text_clean".equals(currentStep)) {
                executeTextCleanStep(taskId);
                executeAIProcessStep(taskId);
                executeTTSGenerateStep(taskId, "cn");
                executeTTSGenerateStep(taskId, "en");
            } else if ("ai_process".equals(currentStep)) {
                executeAIProcessStep(taskId);
                executeTTSGenerateStep(taskId, "cn");
                executeTTSGenerateStep(taskId, "en");
            } else if ("tts_generate_cn".equals(currentStep)) {
                executeTTSGenerateStep(taskId, "cn");
                executeTTSGenerateStep(taskId, "en");
            } else if ("tts_generate_en".equals(currentStep)) {
                executeTTSGenerateStep(taskId, "en");
            }
            
            completeTask(taskId);
            
        } catch (Exception e) {
            log.error("断点恢复失败: taskId={}", taskId, e);
            failTask(taskId, e.getMessage());
        }
    }

    /**
     * 执行指定步骤
     */
    @Override
    public void executeStep(Long taskId, String stepName) 
    {
        log.info("执行步骤: taskId={}, stepName={}", taskId, stepName);
        
        try {
            switch (stepName) {
                case "text_clean":
                    executeTextCleanStep(taskId);
                    break;
                case "ai_process":
                    executeAIProcessStep(taskId);
                    break;
                case "tts_generate_cn":
                    executeTTSGenerateStep(taskId, "cn");
                    break;
                case "tts_generate_en":
                    executeTTSGenerateStep(taskId, "en");
                    break;
                default:
                    log.warn("未知步骤: {}", stepName);
            }
        } catch (Exception e) {
            log.error("步骤执行失败: taskId={}, stepName={}", taskId, stepName, e);
            throw new RuntimeException("步骤执行失败: " + e.getMessage(), e);
        }
    }

    /**
     * 执行文本清理步骤
     */
    private void executeTextCleanStep(Long taskId) {
        log.info("[步骤1] 文本清理开始: taskId={}", taskId);
        
        TaskStep step = taskStepService.selectStepByTaskIdAndName(taskId, "text_clean");
        if (step == null) {
            throw new RuntimeException("步骤不存在: text_clean");
        }
        
        try {
            // 更新任务状态
            updateTaskCurrentStep(taskId, "text_clean", 0);
            
            // 开始步骤
            taskStepService.startStep(step.getStepId());
            
            // 获取文章
            TaskQueue task = taskQueueService.selectTaskQueueByTaskId(taskId);
            NewsArticle article = newsArticleService.selectNewsArticleByArticleId(task.getArticleId());
            
            if (article == null || article.getContent() == null) {
                throw new RuntimeException("文章内容为空");
            }
            
            // 清理文本（复用现有方法）
            String cleanedText = cleanContentText(article.getContent());
            
            // 保存输出
            JSONObject outputData = new JSONObject();
            outputData.put("cleaned_text", cleanedText);
            outputData.put("original_length", article.getContent().length());
            outputData.put("cleaned_length", cleanedText.length());
            
            taskStepService.completeStep(step.getStepId(), outputData.toJSONString());
            
            log.info("[步骤1] 文本清理完成: 原始长度={}, 清理后长度={}", 
                     article.getContent().length(), cleanedText.length());
            
        } catch (Exception e) {
            log.error("[步骤1] 文本清理失败", e);
            taskStepService.failStep(step.getStepId(), e.getMessage());
            throw e;
        }
    }

    /**
     * 执行AI处理步骤
     */
    private void executeAIProcessStep(Long taskId) {
        log.info("[步骤2] AI处理开始: taskId={}", taskId);
        
        TaskStep step = taskStepService.selectStepByTaskIdAndName(taskId, "ai_process");
        if (step == null) {
            throw new RuntimeException("步骤不存在: ai_process");
        }
        
        try {
            // 更新任务状态
            updateTaskCurrentStep(taskId, "ai_process", 0);
            
            // 开始步骤
            taskStepService.startStep(step.getStepId());
            
            // 读取清理后的文本
            TaskStep textCleanStep = taskStepService.selectStepByTaskIdAndName(taskId, "text_clean");
            JSONObject textCleanOutput = JSON.parseObject(textCleanStep.getOutputData());
            String cleanedText = textCleanOutput.getString("cleaned_text");
            
            // 读取任务配置
            TaskQueue task = taskQueueService.selectTaskQueueByTaskId(taskId);
            JSONObject config = JSON.parseObject(task.getConfig());
            List<Long> modelIds = null;
            if (config != null && config.containsKey("ai_model_ids")) {
                modelIds = config.getJSONArray("ai_model_ids").toJavaList(Long.class);
            }
            int parallelLevel = config != null ? config.getIntValue("ai_parallel_level", 5) : 5;
            
            // 并行翻译
            String translated = parallelProcessorService.parallelTranslate(
                taskId, step.getStepId(), cleanedText, "cn", modelIds, parallelLevel);
            
            // 保存到news_content
            NewsContent chineseContent = new NewsContent();
            chineseContent.setArticleId(task.getArticleId());
            chineseContent.setLanguage("cn");
            chineseContent.setContent(cleanedText);
            // 这里简化，实际应该调用AI生成摘要和断句
            chineseContent.setSummary(cleanedText.substring(0, Math.min(100, cleanedText.length())));
            chineseContent.setSentences(JSON.toJSONString(Arrays.asList(cleanedText)));
            chineseContent.setCreateTime(new Date());
            newsContentService.insertNewsContent(chineseContent);
            
            NewsContent englishContent = new NewsContent();
            englishContent.setArticleId(task.getArticleId());
            englishContent.setLanguage("en");
            englishContent.setContent(translated);
            englishContent.setSummary(translated.substring(0, Math.min(100, translated.length())));
            englishContent.setSentences(JSON.toJSONString(Arrays.asList(translated)));
            englishContent.setCreateTime(new Date());
            newsContentService.insertNewsContent(englishContent);
            
            // 保存输出
            JSONObject outputData = new JSONObject();
            outputData.put("translated_text", translated);
            outputData.put("cn_content_id", chineseContent.getContentId());
            outputData.put("en_content_id", englishContent.getContentId());
            
            taskStepService.completeStep(step.getStepId(), outputData.toJSONString());
            
            log.info("[步骤2] AI处理完成");
            
        } catch (Exception e) {
            log.error("[步骤2] AI处理失败", e);
            taskStepService.failStep(step.getStepId(), e.getMessage());
            throw e;
        }
    }

    /**
     * 执行TTS生成步骤
     */
    private void executeTTSGenerateStep(Long taskId, String language) {
        log.info("[步骤TTS] TTS生成开始: taskId={}, language={}", taskId, language);
        
        String stepName = "tts_generate_" + language;
        TaskStep step = taskStepService.selectStepByTaskIdAndName(taskId, stepName);
        if (step == null) {
            throw new RuntimeException("步骤不存在: " + stepName);
        }
        
        try {
            // 更新任务状态
            updateTaskCurrentStep(taskId, stepName, 0);
            
            // 开始步骤
            taskStepService.startStep(step.getStepId());
            
            // 读取句子
            TaskQueue task = taskQueueService.selectTaskQueueByTaskId(taskId);
            NewsContent content = newsContentService.selectNewsContentByArticleIdAndLanguage(
                task.getArticleId(), language);
            
            if (content == null || content.getSentences() == null) {
                throw new RuntimeException("内容或句子不存在: language=" + language);
            }
            
            // 解析句子
            JSONArray sentencesArray = JSON.parseArray(content.getSentences());
            List<String> sentences = sentencesArray.toJavaList(String.class);
            
            // 读取任务配置
            JSONObject config = JSON.parseObject(task.getConfig());
            Long ttsEngineId = config != null ? config.getLong("tts_engine_id") : 1L;
            int parallelLevel = config != null ? config.getIntValue("tts_parallel_level", 5) : 5;
            String voiceName = config != null ? config.getJSONObject("voice_config").getString(language + "_voice") : null;
            
            // 并行TTS
            List<IParallelProcessorService.AudioResult> results = 
                parallelProcessorService.parallelTTS(
                    taskId, step.getStepId(), sentences, language, 
                    ttsEngineId, voiceName, parallelLevel);
            
            // 这里简化，实际应该合并音频并保存到news_audio
            
            // 保存输出
            JSONObject outputData = new JSONObject();
            outputData.put("audio_results", results.stream()
                .map(r -> JSON.toJSONString(r))
                .collect(Collectors.toList()));
            
            taskStepService.completeStep(step.getStepId(), outputData.toJSONString());
            
            log.info("[步骤TTS] TTS生成完成: language={}", language);
            
        } catch (Exception e) {
            log.error("[步骤TTS] TTS生成失败: language={}", language, e);
            taskStepService.failStep(step.getStepId(), e.getMessage());
            throw e;
        }
    }

    /**
     * 完成任务
     */
    private void completeTask(Long taskId) {
        TaskQueue task = new TaskQueue();
        task.setTaskId(taskId);
        task.setStatus("completed");
        task.setCurrentStep(null);
        task.setTotalProgress(100);
        task.setCompletedAt(new Date());
        task.setUpdateTime(new Date());
        taskQueueService.updateTaskQueue(task);
        
        log.info("任务完成: taskId={}", taskId);
    }

    /**
     * 任务失败
     */
    private void failTask(Long taskId, String error) {
        TaskQueue task = new TaskQueue();
        task.setTaskId(taskId);
        task.setStatus("failed");
        task.setErrorMessage(error);
        task.setUpdateTime(new Date());
        taskQueueService.updateTaskQueue(task);
        
        log.error("任务失败: taskId={}, error={}", taskId, error);
    }

    /**
     * 更新任务当前步骤
     */
    private void updateTaskCurrentStep(Long taskId, String stepName, int progress) {
        TaskQueue task = new TaskQueue();
        task.setTaskId(taskId);
        task.setCurrentStep(stepName);
        task.setCurrentStepProgress(progress);
        task.setUpdateTime(new Date());
        taskQueueService.updateTaskQueue(task);
    }

    /**
     * 清理文本内容
     */
    private String cleanContentText(String content) {
        if (content == null || content.isEmpty()) {
            return content;
        }
        
        String cleaned = content;
        
        // 1. 移除HTML标签
        cleaned = cleaned.replaceAll("<[^>]+>", "");
        
        // 2. 统一换行符
        cleaned = cleaned.replaceAll("\\r\\n", "\n");
        cleaned = cleaned.replaceAll("\\r", "\n");
        
        // 3. 移除多余的连续换行符
        cleaned = cleaned.replaceAll("\n{3,}", "\n\n");
        
        // 4. 移除行首行尾的空格
        String[] lines = cleaned.split("\n");
        StringBuilder result = new StringBuilder();
        for (String line : lines) {
            line = line.trim();
            if (!line.isEmpty()) {
                if (result.length() > 0) {
                    result.append("\n");
                }
                result.append(line);
            }
        }
        cleaned = result.toString();
        
        // 5. 移除多余的连续空格
        cleaned = cleaned.replaceAll(" {2,}", " ");
        
        // 6. 移除全角空格
        cleaned = cleaned.replaceAll("　+", "");
        
        // 7. 去除全文首尾空白
        cleaned = cleaned.trim();
        
        return cleaned;
    }
}

